﻿#region using
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Xml;
using Linq2Crm;
using Linq2Crm.ObjectModel;
using Linq2Crm.ObjectModel.DomainObject;
using Linq2Crm.Request;
using Linq2Crm.Request.SpecificRequest;
using SLApp_Test.Model;

#endregion

namespace SLApp_Test
{
   public partial class ViewModel : INotifyPropertyChanged
   {
      private bool _isBusy;
      private Tracer _messager;
      private Random rand = new Random();

      private Employee empl;
      private IEnumerable<View> views;
      private string _busyContent;

      private User _systemUser;

      public string BusyContent
      {
         get { return _busyContent; }
         set
         {
            _busyContent = value;
            OnPropertyChanged("BusyContent");
         }
      }

      public ViewModel()
      {
         DomainObjectContext.IsBusyChanged += (sender, args) => { IsBusy = DomainObjectContext.IsBusy; };

         ExecuteCommand = new SimpleCommand(x => RunCommand(x));                 
      }

      public Tracer Messager
      {
         get { return _messager ?? (_messager = new Tracer()); }
         set { _messager = value; }
      }

      public bool IsBusy
      {
         get { return _isBusy; }
         set
         {
            _isBusy = value;
            OnPropertyChanged("IsBusy");
         }
      }

      public ICommand ExecuteCommand { get; set; }

      #region Implementation of INotifyPropertyChanged
      public event PropertyChangedEventHandler PropertyChanged;

      public void OnPropertyChanged(string name)
      {
         PropertyChangedEventHandler handler = Interlocked.CompareExchange(ref PropertyChanged, null, null);
         if (handler != null)
         {
            Deployment.Current.Dispatcher.BeginInvoke(() => handler(this, new PropertyChangedEventArgs(name)));
         }
      }
      #endregion

      async protected Task RunCommand(object o)
      {
         if (o is string && !string.IsNullOrEmpty((string)o))
         {
            switch ((string)o)
            {
               case "get":

                  #region
                  GetRequest request = GetRequest.Create<Project>();
		            request.Query =
			            RequestBase.CreateQuery<Project>()
			                       .Where(x => x.StateCode == RecordStateCode.Active && x.Customer.Id != Guid.Parse("A0E6B456-F18B-E211-B221-00155D02C13E"));
							

                  GetResponse response = (GetResponse)(await DomainObjectContext.Instance.ExecuteAsync(request));
                  if (!Messager.WriteStatus(response))
                  {
                     return;
                  }
                  Messager.AddLine("Count: " + response.Items.Count());
						//foreach (var domainObject in response.Items)
						//{
						//	Messager.AddLine("Item: " + domainObject.Name);
						//}
                  Messager.CloseLine();
                  #endregion

                  break;
					case "take_skip":

						#region
						GetRequest request25 = GetRequest.Create<Project>();
						request25.Query =
							RequestBase.CreateQuery<Project>()
							.Where(x => x.StateCode == RecordStateCode.Active && x.Customer.Id != Guid.Parse("A0E6B456-F18B-E211-B221-00155D02C13E"))
							.Skip(20).Take(20);

						GetResponse response25 = (GetResponse)(await DomainObjectContext.Instance.ExecuteAsync(request25));
						if (!Messager.WriteStatus(response25))
						{
							return;
						}
						Messager.AddLine("Count: " + response25.Items.Count());
						//foreach (var domainObject in response25.Items)
						//{
						//	Messager.AddLine("Item: " + domainObject.Name);
						//}
						Messager.CloseLine();
						#endregion

						break;

					case "take":

						#region
						GetRequest request26 = GetRequest.Create<Project>();
						request26.Query =
							RequestBase.CreateQuery<Project>()
							.Where(x => x.StateCode == RecordStateCode.Active && x.Customer.Id != Guid.Parse("A0E6B456-F18B-E211-B221-00155D02C13E"))
							.Take(20);

						GetResponse response26 = (GetResponse)(await DomainObjectContext.Instance.ExecuteAsync(request26));
						if (!Messager.WriteStatus(response26))
						{
							return;
						}
						Messager.AddLine("Count: " + response26.Items.Count());
						//foreach (var domainObject in response26.Items)
						//{
						//	Messager.AddLine("Item: " + domainObject.Name);
						//}
						Messager.CloseLine();
						#endregion

						break;

					case "skip":

						#region
						GetRequest request27 = GetRequest.Create<Project>();
						request27.Query =
							RequestBase.CreateQuery<Project>()
							.Where(x => x.StateCode == RecordStateCode.Active && x.Customer.Id != Guid.Parse("A0E6B456-F18B-E211-B221-00155D02C13E"))
							.Skip(20);

						GetResponse response27 = (GetResponse)(await DomainObjectContext.Instance.ExecuteAsync(request27));
						if (!Messager.WriteStatus(response27))
						{
							return;
						}
						Messager.AddLine("Count: " + response27.Items.Count());
						//foreach (var domainObject in response27.Items)
						//{
						//	Messager.AddLine("Item: " + domainObject.Name);
						//}
						Messager.CloseLine();
						#endregion

						break;
               case "getinserted":

                  #region
                  GetRequest request5 = GetRequest.Create<Employee>();
                  request5.Query =
                     RequestBase.CreateQuery<Employee>().Where(x => x.Id == empl.Id);
                  GetResponse response5 = (GetResponse)(await DomainObjectContext.Instance.ExecuteAsync(request5));
                  if (!Messager.WriteStatus(response5) || !response5.Items.Any())
                  {
                     return;
                  }
                  empl = (Employee)response5.Items.First();
                  Messager.AddRecieved(empl.Name);
                  Messager.CloseLine();

                  #endregion

                  break;
               case "createemployee":

                  #region
                  empl = new Employee
                     {
                        FirstName = "LINQ test 1",
                        LastName = "Some last name"
                     };
                  InsertRequest request1 = InsertRequest.Create<Employee>(empl);
                  var response1 = (InsertResponse)await DomainObjectContext.Instance.ExecuteAsync(request1);
						
                  if (!Messager.WriteStatus(response1))
                  {
                     return;
                  }
                  Messager.CloseLine();
                  #endregion

                  break;
               case "deletelastcreatedemployee":

                  #region
                  DeleteRequest request2 = DeleteRequest.Create<Employee>(empl);
                  var response2 = (DeleteResponse)await DomainObjectContext.Instance.ExecuteAsync(request2);
						
                  if (!Messager.WriteStatus(response2))
                  {
                     return;
                  }
                  Messager.CloseLine();

                  #endregion

                  break;
               case "deactivatelastemployee":

                  #region
                  SetStatusRequest requests = SetStatusRequest.Create<Employee>(empl, RecordStateCode.Inactive, -1);
                  var responses = await DomainObjectContext.Instance.ExecuteAsync(requests);
                  if (!Messager.WriteStatus(responses))
                  {
                     return;
                  }
                  Messager.CloseLine();
                  #endregion

                  break;
               case "test":
                  Messager.Start();
                  var appStatuses = await DomainObjectContext.Instance.GetStatusesAsync<Appointment>();
                  var tasks = await DomainObjectContext.Instance.GetStatusesAsync<SLApp_Test.Model.AppTask>();
                  Messager.AddLine("Appointments: ");
                  foreach (KeyValuePair<RecordStateCode, Dictionary<int, string>> pair in appStatuses.Item1)
                  {
                     Messager.AddLine(pair.Key.ToString());
                     foreach (KeyValuePair<int, string> valuePair in pair.Value)
                     {
                        Messager.AddLine(string.Format("\t{0}:{1}", valuePair.Value, valuePair.Key));
                     }
                  }
                  Messager.AddLine("Tasks: ");
                  foreach (KeyValuePair<RecordStateCode, Dictionary<int, string>> pair in tasks.Item1)
                  {
                     Messager.AddLine(pair.Key.ToString());
                     foreach (KeyValuePair<int, string> valuePair in pair.Value)
                     {
                        Messager.AddLine(string.Format("\t{0}:{1}", valuePair.Value, valuePair.Key));
                     }
                  }
                  Messager.CloseLine();
                  break;
               case "updatelastemployee":

                  #region
                  empl.Name = empl.StatusCode + empl.Name + empl.StatusCode;
                  UpdateRequest request3 = UpdateRequest.Create<Employee>(empl);
                  var response3 = await DomainObjectContext.Instance.ExecuteAsync(request3);
                  if (!Messager.WriteStatus(response3))
                  {
                     return;
                  }
                  Messager.CloseLine();

                  #endregion

                  break;
               case "getjoin":

                  #region
                  GetRequest emp = GetRequest.Create<ProjectAssignment>();
                  emp.Query = RequestBase.CreateQuery<ProjectAssignment>().Join(new List<Booking>(),
                                                                                em => em.Id,
                                                                                booking => booking.ProjectAssignmentId,
                                                                                (assignment, booking) => assignment.StateCode == RecordStateCode.Active);

                  GetResponse empResponse = (GetResponse)(await DomainObjectContext.Instance.ExecuteAsync(emp));
                  if (!Messager.WriteStatus(empResponse))
                  {
                     return;
                  }
                  ProjectAssignment eee = (ProjectAssignment)empResponse.Items.FirstOrDefault();
                  Messager.AddRecieved("Project " + eee.Name);
                  if (eee.Booking != null)
                  {
                     Messager.AddLine("Joined booking:  " + eee.Booking.Name);
                  }
                  Messager.CloseLine();
                  #endregion

                  break;
               case "getleftjoin":

                  #region
                  GetRequest empJoin = GetRequest.Create<ProjectAssignment>();
                  empJoin.Query = RequestBase.CreateQuery<ProjectAssignment>().LeftJoin(new List<Booking>(),
                                                                                em => em.Id,
                                                                                booking => booking.ProjectAssignmentId,
                                                                                (assignment, booking) => assignment.StateCode == RecordStateCode.Active);

                  GetResponse empJoinResponse = (GetResponse)(await DomainObjectContext.Instance.ExecuteAsync(empJoin));
                  if (!Messager.WriteStatus(empJoinResponse))
                  {
                     return;
                  }
                  ProjectAssignment eJoined = (ProjectAssignment)empJoinResponse.Items.FirstOrDefault();
                  Messager.AddRecieved("Project " + eJoined.Name);
                  if (eJoined.Booking != null)
                  {
                     Messager.AddLine("Joined booking:  " + eJoined.Booking.Name);
                  }
                  Messager.CloseLine();
                  #endregion

                  break;
               case "whoami":

                  #region
                  WhoAmIRequestWrapper who = WhoAmIRequestWrapper.Create();
                  WhoAmIResponseWrapper whoResponse = (WhoAmIResponseWrapper)(await DomainObjectContext.Instance.ExecuteAsync(who));
                  if (!Messager.WriteStatus(whoResponse))
                  {
                     return;
                  }
						
                  Messager.AddLine("UserId: " + whoResponse.UserId);
                  Messager.AddLine("OrgId: " + whoResponse.OrganizationId);

                  _systemUser = new User()
                     {
                        UserSettings = whoResponse.UserSettings,
                        Id = whoResponse.UserId,
								BusinessUnitId = whoResponse.BusinessUnitId,
								OrganizationId = whoResponse.OrganizationId
                     };
                  foreach (System.Collections.Generic.KeyValuePair<string, object> userSetting in whoResponse.UserSettings)
                  {
                     Messager.AddLine(userSetting.Key + ": " + userSetting.Value);
                  }
                  Messager.CloseLine();
                  #endregion

                  break;
               case "getviews":

                  #region 
                  GetViewRequest gv = GetViewRequest.CreateFor<Project>(true);
                  GetViewResponse gvr = (GetViewResponse) (await DomainObjectContext.Instance.ExecuteAsync(gv));

                  if (!Messager.WriteStatus(gvr))
                  {
                     return;
                  }
                  Messager.AddLine(string.Format("\t ====Count: {0} ===", gvr.Views.Count()));
                  Messager.AddLine("");

                  foreach (View view in gvr.Views)
                  {
                     Messager.AddLine(string.Format("Name: {0}", view.Name));
                     Messager.AddLine(string.Format("\tQuery type: {0}", view.QueryType));
                     Messager.AddLine(string.Format("\tReturned type code: {0}", view.ReturnedTypeCode));
                     Messager.AddLine(string.Format("\tView guid: {0:b}", view.Id));
                     Messager.AddLine("");
                  }
                  views = gvr.Views;
                  Messager.CloseLine();
                  #endregion

                  break;
               case "getdefaultviewforproject":

                  #region 
//                  Messager.Start();
//                  if (_systemUser == null)
//                  {
//                     Messager.AddLine("Run 'WhoAmI request'");
//                     Messager.CloseLine();
//                     return;
//                  }
//                  var id = await DomainObjectContext.Instance.GetDefaultViewIdByUserSettings<Project>(_systemUser.UserSettings);
//                  Messager.AddLine(string.Format("Default view id: {0:b}", id));
//                  Messager.CloseLine();
                  #endregion

                  break;
               case "getprojectswithrandomview":

                  #region 
                  GetRequest gr = GetRequest.Create<Project>();
                  gr.Query = GetRequest.CreateQuery<Project>().Where(x => x.ParentProject == null);

                  var usedView = views.ToArray()[rand.Next(0, views.Count())];
                  Messager.AddLine(string.Format("Random view: {0}", usedView.Name));
                  gr.UseView = usedView;
                  GetResponse gsvrs = (GetResponse) (await DomainObjectContext.Instance.ExecuteAsync(gr));
                  if (!Messager.WriteStatus(gsvrs))
                  {
                     return;
                  }
                  Messager.AddLine("Count: " + gsvrs.Items.Count());
                  Messager.CloseLine();
                  #endregion

                  break;
               case "invoice_createtestdata":
                  try
                  {
                     Messager.AddLine("-----=======Creating invoice test data=======-------");
                     await CreateInvoiceTestData();
                  }
                  catch (Exception e)
                  {
                     Messager.AddLine("Exception occured:" + e.Message);
                  }
                  finally
                  {
                     Messager.AddLine("-----=======DONE=======-----");
                     Messager.CloseLine();
                  }
                  break;
               case "invoice_cleanup":
                  try
                  {
                     Messager.AddLine("-----=======Clean up after invoice=======-----");
                     await CleanUpInvoiceTestData();
                  }
                  catch (Exception e)
                  {
                     Messager.AddLine("Exception occured:" + e.Message);
                  }
                  finally
                  {
                     Messager.AddLine("-----=======DONE=======-----");
                     Messager.CloseLine();
                  }
                  break;
               default:
                  return;
            }
         }
         else
         {
            Messager.AddLine("Command is unknown");
         }
      }
   }
}